<template>
    <div class="timeline" :class="{ 'disabled': true }">
       
        <div class="timeline-scale" @mousedown="onDragStart">
            <canvas class="timeline-scale-marks" ref="marks" width=212 height=35></canvas>
            <div class="timeline-scale-pointer"
                :style="{ left: pointerPosition + 'px' }"
                    @mousedown.stop="onPointerDragStart">
                <div class="timeline-scale-pointer-belt" :style="{ width: pointerPosition + 1 + 'px'}">
                </div>
                <div class="timeline-scale-pointer-button"></div>
            </div>
        </div>

    </div>
</template>

<script>
function format( timestamp, exceptObjet ) {
    const date = new Date( timestamp )
    let Y = date.getFullYear();
    let M = date.getMonth() + 1;
    let D = date.getDate();
    let h = date.getHours();
    let m = date.getMinutes();
    let s = date.getSeconds();

    M = M < 10 ? '0' + M : M;
    D = D < 10 ? '0' + D : D;
    h = h < 10 ? '0' + h : h;
    m = m < 10 ? '0' + m : m;
    s = s < 10 ? '0' + s : s;

    if ( exceptObjet ) {
        return {
            year: `${Y}-${M}-${D}`,
            date: `${M}-${D}`,
            time: `${h}:${m}`
        }
    }

    return `${Y}-${M}-${D} ${h}:${m}`;
}

function updateMarks( canvas, data, colorGradients) {

    if ( !canvas ) return;

    canvas.width = canvas.clientWidth;
    canvas.height = canvas.clientHeight;

    const width = canvas.width - 32;

    const context = canvas.getContext( '2d', { alpha: true } );

    context.fillStyle = '#fff';
    //context.fillRect( 0, 0, canvas.width, canvas.height );

    context.translate( 14, 5 );

    
    context.beginPath();
    let linearGradient = context.createLinearGradient(0,0,180+2,0)
    for( let i = 0; i < 15; i++){
        context.moveTo( i * 12 , 0 );
        linearGradient.addColorStop(i * 12/180  , colorGradients[i])
    }
    context.fillStyle = linearGradient
    context.rect(-1,-6,180+2,20);
    context.fill();

    context.beginPath();
    context.strokeStyle = '#000';
    const start = data.start;
    const end = data.end;

    const scale = 30;
    const scale5 = scale / 5;
    for ( var i = 0; i <= width; i += scale ) {

        context.moveTo( i, 0 );
        context.lineTo( i, 8 );
        // context.rect(i,i,10,10);

        if ( i === width ) break;

        for ( var k = 1; k <= 4; k++ ) {
            context.moveTo( i + ( scale5 * k ), 2 );
            context.lineTo( i + ( scale5 * k ), 6 );
        }

    }

    context.stroke();

    context.font = '10px Arial';
    context.fillStyle = '#000'
    context.textAlign = 'center';

    for ( var i = 0; i <= width; i += scale * 2 ) {
        context.fillText( start + i / width * ( end - start ) + 'min', i, 25 );
    }

}

export default {
    name: 'timeline',
    props: {
        disabled: {
            type: Boolean,
            default: false
        },
        start: {
            type: Number,
            default: 0
        },
        end: {
            type: Number,
            default: 30
        },
        min: {
            type: Number,
            default: 0
        },
        value: Number,
        loop: {
            type: Boolean
        },
        colorGradients:{
            type: Array,
            default: function () {
                return ["#d53e4f","#e27d67","#e99d73",
                        "#f0bd7f","#f7dd8b","#fefc98",
                        "#e8f2a2","#cfe5ac","#b2d5b8",
                        "#9ac7c2","#81bacc","#69acd5",
                        "#599aca","#4889be","#3777b3"]
            }
        }
    },
    data () {
        return {
            val: this.value || this.start
        }
    },
    computed: {
        pointerPosition () {           
            return ( this.val - this.start ) / this.unitLength
        },
        unitLength () {
            return ( this.end - this.start ) / 180;
        },
        offsetLeft() {
            const rect = this.$refs.marks.getBoundingClientRect()
            return rect.left + 16;
        },
        step() {
            return ( this.end - this.start ) / 100;
        },
        beltBgStyle () {
            return "#ff0000"
        }
    },
    watch: {
        start () {
            this.update()
        },
        end () {
            this.update()
        },
        value ( val ) {
            this.val = val;
            this.update();
        },
        val ( val ) {
            this.$emit( 'input', val );
        }
    },
    mounted () {
        window.addEventListener( 'resize', () => {
            this.update()
        }, false )

        setTimeout( () => {
            const canvas = this.$refs.marks;
            updateMarks( canvas, {
                start: this.start,
                end: this.end,
                unit: 60
            }, this.colorGradients )
        }, 20 )
    },
    methods: {
        update() {
            updateMarks( this.$refs.marks, {
                start: this.start,
                end: this.end,
                unitLength: this.unitLength
            } , this.colorGradients )
        },
        onDragStart( e ) {
            let val = ( e.clientX - this.offsetLeft ) * this.unitLength + this.start;
            val = this.step * Math.floor( val / this.step );
            this.val = Math.max( Math.min( val, this.end ), this.start )
            window.addEventListener( 'mousemove', this.onDragMove, false )
            window.addEventListener( 'mouseup', this.onDragEnd, false )
        },
        onDragMove( e ) {
            let val = ( e.clientX - this.offsetLeft ) * this.unitLength + this.start;
            val = Math.max(this.min, this.step * Math.floor( val / this.step ));
            this.val = Math.max( Math.min( val, this.end ), this.start )
        },
        onDragEnd( e ) {
            this.$emit( 'change', this.val );
            window.removeEventListener( 'mousemove', this.onDragMove, false )
            window.removeEventListener( 'mouseup', this.onDragEnd, false )
        },
        onPointerDragStart( e ) {
            this.dragStart = e.clientX;
            this.valueStart = this.val;
            window.addEventListener( 'mousemove', this.onPointerDragMove, false )
            window.addEventListener( 'mouseup', this.onPointerDragEnd, false )
        },
        onPointerDragMove( e ) {
            let val = this.valueStart + ( e.clientX - this.dragStart ) * this.unitLength;
            val = Math.max(this.min, this.step * Math.floor( val / this.step ));
            this.val = Math.max( Math.min( val, this.end ), this.start )
        },
        onPointerDragEnd( e ) {
            this.$emit( 'change', this.val );
            window.removeEventListener( 'mousemove', this.onPointerDragMove, false )
            window.removeEventListener( 'mouseup', this.onPointerDragEnd, false )
        }

    },
}
</script>

<style lang="scss">

.timeline {
    height: 44px;
    border-radius: 3px;
    user-select: none;
    width: 212px;
    position: relative;

    &::after {
        content: '';
        display: none;
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        z-index: 10;
    }

    &.disabled {
        opacity: .8;
    }
}

.timeline-scale {
    display: block;
    float: left;
    width: 212px;
    position: relative;
    height: 100%;
    // overflow: hidden;
}

.timeline-scale-marks {
    margin-top: 5px;
}
.timeline-scale-pointer {
    position: absolute;
    top: 0;
    bottom: 0;
    // height: 100%;
    width: 2px;
    margin-left: 12px;
    background: #4087f7;
    user-select: none;
}

.timeline-scale-pointer-belt {
    position: absolute;
    z-index: -1;
    right: 0;
    top: 5px;
    height: 18px;
    background: linear-gradient(right,rgba(#FFDEAD,1) 10px,rgba(#FF4500,1) 20px);
}

.timeline-scale-pointer-button {
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: #4087f7;
    white-space: nowrap;
    position: absolute;
    top: 4px;
    margin-left: -9px;
    cursor: pointer;

    &::after {
        content: '';
        width: 8px;
        height: 8px;
        border-radius: 50%;
        display: block;
        position: absolute;
        top: 6px;
        left: 6px;
        background: #fff;
    }
}
</style>
